package com.feinno.urcs.group.http.handler;

import com.feinno.sip.header.ims.PAssertedIdentityHeader;
import com.feinno.urcs.group.GroupConstants;
import com.feinno.urcs.group.GroupError;
import com.feinno.urcs.group.GroupException;
import com.feinno.urcs.group.api.GroupService;
import com.feinno.urcs.group.entity.GroupIndex;
import com.feinno.urcs.group.entity.GroupInfo;
import com.feinno.urcs.group.http.servlet.BaseHttpServlet;
import com.feinno.urcs.group.http.servlet.GroupHttpContext;
import com.feinno.urcs.group.http.util.HttpHelper;
import com.feinno.urcs.group.pd.upstream.entity.PublicGroupList;
import com.feinno.urcs.types.MobileNo;
import com.feinno.util.Tuple3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.URI;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by wuzhiguo on 15-5-14.
 */
public class GetGroupListHandler extends BaseHttpServlet {

	private static final Logger LOGGER = LoggerFactory.getLogger(GetGroupListHandler.class);

	@Override
	public void process(final GroupHttpContext ctx) throws IOException {
		try {
			if (LOGGER.isInfoEnabled()) {
				String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
				LOGGER.info(String.format("Received Request: %s", requestString));
			}

			if (!ctx.getSenderIMPU().equals(ctx.getXuiIMPU())) {
				String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
				LOGGER.error(String.format("senderIMPU not equals xuiIMPU. Received Request: %s", requestString));
				ctx.getResponse().sendError(400, "ArgsError");
				return;
			}

			// 调用GroupService
			MobileNo mobileNo = MobileNo.parseFrom(ctx.getXuiIMPU().getUser());
			List<Integer> groupIdList = ctx.getGroupService().getGroupList(mobileNo);
			List<Tuple3<Integer, String, Boolean>> infoList = new ArrayList<>();
			ctx.getFxDataValidateService().loadData(mobileNo);

			for (int groupId : groupIdList) {
				try {
					GroupInfo groupInfo = ctx.getGroupService().getGroupInfo(ctx.getGroupService().getGroupIndex(groupId));
					String name = groupInfo.getSubject();
					boolean isAdmin = groupInfo.getGroupAdmin().equals(mobileNo);
					Tuple3<Integer, String, Boolean> Tuple3 = new Tuple3<>(groupId, name, isAdmin);
					infoList.add(Tuple3);
				} catch (Exception e) {
					LOGGER.error(String.format("GroupList error MobileNo=%s GroupId=%s", mobileNo, groupId), e);
				}
			}

			String verStr = ctx.getRequest().getHeader("If-None-Match");
			int version = Integer.parseInt(null == verStr ? "0" : verStr);
			int curGrpListVer = 0;
			if (version == 0) {
				ctx.getGroupListVersionCacheManager().resetGrpListVer(mobileNo);
				curGrpListVer = ctx.getGroupListVersionCacheManager().incGrpListVer(mobileNo);
			} else {
				curGrpListVer = ctx.getGroupListVersionCacheManager().getCurGrpListVer(mobileNo);
			}
			byte[] responseBody = null;
			if (version == 0 || version != curGrpListVer) {
				responseBody = buildResponseBody(infoList, ctx.getGroupService());
				ctx.getResponse().setStatus(200);
			} else {
				responseBody = new byte[0];
				ctx.getResponse().setStatus(304);
			}
			setDigestAuthenticationInfo(ctx);
			ctx.getResponse().setContentType("application/public-group-list+xml; charset=\"utf-8\"");
			ctx.getResponse().setHeader("ETag", String.valueOf(curGrpListVer));
			ctx.getResponse().setContentLength(responseBody.length);
			ctx.getResponse().getOutputStream().write(responseBody);
			ctx.getResponse().getOutputStream().flush();

			if (LOGGER.isInfoEnabled()) {
				String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
				String responseBodyString = new String(responseBody);
				LOGGER.info(String.format("process() Successfully.\n"
								+ "Received Request: %s\n"
								+ "Send Response Body: %s",
						requestString,
						responseBodyString));
			}

		} catch (GroupException gex) {
			GroupError error = gex.getError();
			String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
			LOGGER.error(String.format("process() GroupException. GroupError Code: %s Received Request: %s",
					error.getSipCode(), requestString), gex);
			ctx.getResponse().sendError(error.getSipCode(), "GroupError");
		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
			LOGGER.error(String.format("process() Error. Received Request: %s", requestString), ex);
			ctx.getResponse().sendError(500, "ServerError");
		}
	}

	private byte[] buildResponseBody(List<Tuple3<Integer, String, Boolean>> infoList, GroupService groupService) throws Exception {
		PublicGroupList publicGroupList = new PublicGroupList();
		List<PublicGroupList.PublicGroupListInfo> grpupList = new ArrayList<>();

		if (infoList != null && infoList.size() > 0) {
			for (Tuple3<Integer, String, Boolean> Tuple3 : infoList) {
				PublicGroupList.PublicGroupListInfo p = new PublicGroupList.PublicGroupListInfo();
				GroupIndex groupIndex = groupService.getGroupIndex(Tuple3.getV1());
				if (groupIndex == null) {
					LOGGER.warn(String.format("getGroupIndex error , groupId : %s", Tuple3.getV1()));
					continue;
				}
				String groupUri = groupIndex.getConferenceUri();
				p.setUri(String.format(GroupConstants.PUBLIC_GROUP_IDENTIFIER_TEMPLATE, groupUri));
				p.setName(Tuple3.getV2());
				p.setIsAdmin(Tuple3.getV3());
				grpupList.add(p);
			}
		}
		publicGroupList.setGrpupList(grpupList);
		return publicGroupList.toXmlByteArray();
	}
}
